#version 450

#define MAX_SAMPLE_RADIUS 25.0
#define RSM_SIZE 256
#define VPL_NUM 32

layout (binding = 0) uniform sampler2D mrtPositionImage;
layout (binding = 1) uniform sampler2D mrtNormalImage;
layout (binding = 2) uniform sampler2D mrtAlbedoImage;

layout (binding = 3) uniform sampler2D rsmPositionImage;
layout (binding = 4) uniform sampler2D rsmNormalImage;
layout (binding = 5) uniform sampler2D rsmFluxImage;

layout (binding = 6) uniform UBO
{
	mat4 cameraView;
	mat4 lightProj;
	mat4 lightView;
	vec4 lightData;
	vec3 lightDir;
	int debugIndex;
} ubo;

layout(std140, binding = 7) uniform SampleCoordsAndWeights
{
	vec4 data[VPL_NUM];
} sampleCoordsAndWeights;

layout (location = 0) in vec2 inUV;

layout (location = 0) out vec4 outColor;

vec3 CalcVplIrradiance(vec3 vplFlux, vec3 vplNormal, vec3 vplPosition, vec3 viewSpacePosition, vec3 viewSpaceNormal, float weight)
{
	vec3 vpl2Frag = normalize(viewSpacePosition - vplPosition);
	return vplFlux * max(dot(vplNormal, vpl2Frag), 0) * max(dot(viewSpaceNormal, -vpl2Frag), 0) * weight;
}

void main() 
{
	vec3 viewSpacePosition = texture(mrtPositionImage, inUV).xyz;
	vec3 viewSpaceNormal = normalize(texture(mrtNormalImage, inUV).xyz);
	vec3 viewSpaceAlbedo = texture(mrtAlbedoImage, inUV).rgb;

	vec4 lightSpacePosition = ubo.lightProj * ubo.lightView * inverse(ubo.cameraView) * vec4(viewSpacePosition, 1.0);
	lightSpacePosition /= lightSpacePosition.w;
	vec2 ndcSpacePosition = (lightSpacePosition.xy + 1) / 2.0;

	vec3 directIllumination = vec3(0.0);
	if(lightSpacePosition.z < 0.0 || lightSpacePosition.z > 1.0 || lightSpacePosition.x > 1.0f || lightSpacePosition.y > 1.0f || lightSpacePosition.x < -1.0f || lightSpacePosition.y < -1.0f )
	{
		directIllumination = vec3(0.1) * viewSpaceAlbedo;
	}
	else
	{
		directIllumination = viewSpaceAlbedo * max(dot(-ubo.lightDir, viewSpaceNormal), 0.1) * 0.5;
		// directIllumination = directIllumination * ubo.lightData.rgb * ubo.lightData.a;
	}

	float rsmTexelSize = 1.0 / RSM_SIZE;
	
//	vec2 tempSamplePos = ndcSpacePosition;// + MAX_SAMPLE_RADIUS * rsmTexelSize;
//	vec3 tempFlux = texture(rsmFluxImage, tempSamplePos).rgb;
//	vec3 tempViewSpaceNormal = normalize(texture(rsmNormalImage, tempSamplePos).xyz);
//	vec3 tempViewSpacePosition = texture(rsmPositionImage, tempSamplePos).xyz;
//
//
//	outColor = vec4(tempFlux, 1.0);
//	return;
//
//	if(tempSamplePos.x > 0.0 && tempSamplePos.y > 0.0 && tempSamplePos.x < 1.0 && tempSamplePos.y < 1.0)
//		outColor = vec4(tempFlux, 1.0);
//	else
//		outColor = vec4(0.0, 0.0, 0.0, 1.0);
//
//	return;
	
	vec3 indirectIllumination = vec3(0.0);
	for(int i = 0; i < VPL_NUM; ++i)
	{
		vec3 vplSampleCoordAndWeight = sampleCoordsAndWeights.data[i].xyz;
		vec2 vplSamplePos = ndcSpacePosition + MAX_SAMPLE_RADIUS * vplSampleCoordAndWeight.xy * rsmTexelSize;
		vec3 vplFlux = texture(rsmFluxImage, vplSamplePos).rgb;
		vec3 vplViewSpaceNormal = normalize(texture(rsmNormalImage, vplSamplePos).xyz);
		vec3 vplViewSpacePosition = texture(rsmPositionImage, vplSamplePos).xyz;

		indirectIllumination += CalcVplIrradiance(vplFlux, vplViewSpaceNormal, vplViewSpacePosition, viewSpacePosition, viewSpaceNormal, vplSampleCoordAndWeight.z);
	}
	indirectIllumination = ubo.lightData.rgb * ubo.lightData.a * viewSpaceAlbedo * indirectIllumination;
	// indirectIllumination /= float(VPL_NUM);

	vec3 result = directIllumination + indirectIllumination;

	outColor = vec4(result, 1.0);

	if(ubo.debugIndex == 1)
		outColor = vec4(indirectIllumination, 1.0);

	if(ubo.debugIndex == 2)
		outColor = vec4(directIllumination, 1.0);

	// directIllumination = texture(rsmNormalImage, inUV).rgb;
	// outColor = vec4(directIllumination, 1.0);
}